package seedmarket

import org.springframework.dao.DataIntegrityViolationException
import org.compass.core.engine.SearchEngineQueryParseException

/**
 * The controller for the Seed domain class
 * @author Gregory Koutrelakos
 * @version 7.11.12
 *
 */
class SeedController {
    
    /**
     *Allows for wildcard searches so that if only a portion of the search
     * query is input that searchable will pull up the entire search query.
     */
    static String WILDCARD = "*"

	/**
	 * Allows all methods at this point
	 */
    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

	/**
	 * The main index method which will be the default if question
	 * @return the list of seeds
	 */
    def index() {
        redirect(action: "list", params: params)
    }

	/**
	 * Displays the list of current seeds in the database
	 * @return the list of seeds
	 */
    def list() {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        [seedInstanceList: Seed.list(params), seedInstanceTotal: Seed.count()]
    }

	/**
	 * Will create a new seed instance
	 * @return new seed instance with taken in parameters
	 */
    def create() {
        [seedInstance: new Seed(params)]
    }

	/**
	 * Saves the seed to the database. Checks if instance is true, then it displays the message if saved or not
	 * @return the saved seed page
	 */
    def save() {
        def seedInstance = new Seed(params)
        if (!seedInstance.save(flush: true)) {
            render(view: "create", model: [seedInstance: seedInstance])
            return
        }

		flash.message = message(code: 'default.created.message', args: [message(code: 'seed.label', default: 'Seed'), seedInstance.id])
        redirect(action: "show", id: seedInstance.id)
    }

	/**
	 * Shows the current seed. Checks to see if the seed is valid, then displays its information.
	 * @return the displayed seed
	 */
    def show() {
        def seedInstance = Seed.get(params.id)
        if (!seedInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'seed.label', default: 'Seed'), params.id])
            redirect(action: "list")
            return
        }

        [seedInstance: seedInstance]
    }

	/**
	 * Edits the seed. Checks for validation then allows editing or not. Is used in update so return null
	 * @return null
	 */
    def edit() {
        def seedInstance = Seed.get(params.id)
        if (!seedInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'seed.label', default: 'Seed'), params.id])
            redirect(action: "list")
            return
        }

        [seedInstance: seedInstance]
    }

	/**
	 * Updates the seed. Checks for validity then will change the parameters if seed is valid. Works with the edit method
	 * @return the updated seed
	 */
    def update() {
        def seedInstance = Seed.get(params.id)
        if (!seedInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'seed.label', default: 'Seed'), params.id])
            redirect(action: "list")
            return
        }
		//if version is valid, creates revisions
        if (params.version) {
            def version = params.version.toLong()
            if (seedInstance.version > version) {
                seedInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                          [message(code: 'seed.label', default: 'Seed')] as Object[],
                          "Another user has updated this Seed while you were editing")
                render(view: "edit", model: [seedInstance: seedInstance])
                return
            }
        }
		//applies revisions
        seedInstance.properties = params

        if (!seedInstance.save(flush: true)) {
            render(view: "edit", model: [seedInstance: seedInstance])
            return
        }

		flash.message = message(code: 'default.updated.message', args: [message(code: 'seed.label', default: 'Seed'), seedInstance.id])
        redirect(action: "show", id: seedInstance.id)
    }

	/**
	 * Deletes the seed. Checks for validity then tries to delete the seed. Exception thrown if data intrgrity is false
	 * @return
	 */
    def delete() {
        def seedInstance = Seed.get(params.id)
        if (!seedInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'seed.label', default: 'Seed'), params.id])
            redirect(action: "list")
            return
        }

        try {
            seedInstance.delete(flush: true)
			flash.message = message(code: 'default.deleted.message', args: [message(code: 'seed.label', default: 'Seed'), params.id])
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e) {
			flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'seed.label', default: 'Seed'), params.id])
            redirect(action: "show", id: params.id)
        }
    }
    
    /**
    * Searches for seeds. This method also takes into account wildcards so that portions of the search field can be input and still pull up a result.
    */
    def search = {
        if(!params.q?.trim()) {
            return[:]
        }
        try {
            String searchTerm = WILDCARD+ params.q + WILDCARD
            return[searchResult: Seed.search(searchTerm,params)]
        } catch (SearchEngineQueryParseException ex) {
            return [parseException:true]
        }
    }
    
    /**
    * Indexes all the results of the search
    */
    def indexAll= {
        Thread.start{
            searchableService.index()
        }
        render("bulk index started in a background thread")
    }
    
    /**
    * Unindexes all the results of the search.
    */
    def unindexAll = {
        searchableService.unindex()
        render("unindexAll done")
    }
}
